using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Xml;
using System.Xml.XPath;
using Mpi.Common.Collections;
using System.Net;
using Xeml.Document.Contracts;
using Mpi.Common;
using System.Diagnostics;
using System.Collections.ObjectModel;
using Xeml.Document.Manager;

namespace Xeml.Document.EnvironmentalOntology
{
    public class EnvironmentOntologyHandler : IDynamicOntologyHandler, IHierarchicalView
    {
        private const string uri = "http://www.mpimp-golm.mpg.de/2007/XEML/Environment";

        #region Fields
        private string instanceLocation;
        IDocument currentDoc;
        private List<IDynamicOntologyTerm> _varSpecs;

        private bool reloadNeeded = true;
        private string nameSpace;

        //private string nameSpaceUri;
        private Dictionary<string, NamedTypeSpecification> globalTypes;
        private Dictionary<string, UnitSet> globalUnits;
        private Dictionary<string, string> contextCollection;
        #endregion

        #region PropertyDefines
        private List<IDynamicOntologyTerm> VariableSpecs
        {
            get
            {
                return this._varSpecs;
            }
        }

        private const string xmlNs = "http://www.mpimp-golm.mpg.de/2007/XEML/Environment";

        public string NameSpace
        {
            get { return nameSpace; }
            private set { nameSpace = value; }
        }

        public string Uri
        {
            get { return uri; }
        }

        private string _ontologyLoadMessage;
        public string OntologyLoadMessage
        {
            get
            {
                return _ontologyLoadMessage;
            }
        }

        private OntologyLoadState _ontologyLoadState = OntologyLoadState.Unloaded;
        /// <summary>
        /// Indicates the load state fo the ontology.
        /// </summary>
        public OntologyLoadState OntologyLoadState
        {
            get
            {
                return _ontologyLoadState;
            }
        }

        public OntologyType OntologyType
        {
            get { return OntologyType.Environment; }
        }

        public string InstanceLocation
        {
            get
            {
                return this.instanceLocation;
            }
            set
            {
                if (this.instanceLocation != value)
                {
                    Debug.WriteLine("EnvionOntologyHandler: OldLocaction=" + instanceLocation);
                    Debug.WriteLine("EnvionOntologyHandler: NewLocaction=" + value);
                    Debug.WriteLine("EnvionOntologyHandler. Set locatoion to:" + value);
                    _ontologyLoadState = OntologyLoadState.ReloadNeeded;
                    _ontologyLoadMessage = "Reload needed";
                    this.instanceLocation = value;
                    this.reloadNeeded = true;
                    //Load();
                }
            }
        }

        public string Publisher
        {
            get
            {
                return "Max Planck Institute of Molecular Plant Physiology, Potsdam/Golm, Germany";
            }
        }

        private Version _version = new Version(1, 0, 0, 0);
        public Version Version
        {
            get
            {
                return _version;
            }
        }

        public string ComponentName
        {
            get { return "Xeml Environment Ontology Handler"; }
        }

        public string Author
        {
            get { return "Jan Hannemann"; }
        }

        public string Description
        {
            get { return "The XEML framework standard component for the definiton of variables for environmental  conditions. This component handles ontologies of the XEO Xml dialect."; }
        }
        #endregion

        /// <summary>
        /// The default contructor.
        /// </summary>
        public EnvironmentOntologyHandler()
        {
            this._varSpecs = new List<IDynamicOntologyTerm>();
            //  _readOnlySupervisors = new ReadOnlyCollection<IVariableSupervisor>(this._varSpecs);
            this.globalTypes = new Dictionary<string, NamedTypeSpecification>();
            this.globalUnits = new Dictionary<string, UnitSet>();
            this.contextCollection = new Dictionary<string, string>();
        }

        #region Validation Methods
        //public void Validate(IDocument xemlDoc)
        //{
        //    this.currentDoc = xemlDoc;
        //    //ValidationMessage vm = new ValidationMessage(SeverityCode.Warning, "This is beta validation module", "XemlParameterRessource", false);
        //    Load(_alias, false);
        //    //OnValidation(vm);
        //    ValidateProperties();

        //    foreach (XeoTerm psup in this._varSpecs)
        //    {
        //        psup.ValidateSupervisedProperties();
        //    }

        //    //this.ValidateDataTypes();
        //    //ValidateCyclingBit();
        //    //ValidateConstBit();
        //    //ValidateRequiredBit();
        //    // ValidateUseAlso();
        //}

        private void ValidateProperties()
        {
            ValidationMessage vm;
            foreach (XeoTerm pd in this._varSpecs)
            {
                //if (pd.IsComposite)
                //{
                foreach (TreeNode<StoryBase> tn in currentDoc.StoryBoard.VirtualRoot.SubNodes(false))
                {

                    string key = pd.TermId;//.NameSpace + ":" + pd.Name;
                    if (tn.Content.Variables.Contains(key))
                    {
                        //  ValidateProperty(tn.Content, tn.Content.Parameters.Find(key), pd);

                        ////if (tn.Content.Parameters[key].IsComposite)
                        ////{
                        ////    if (tn.Content.Parameters[key].DefaultProperty.Name != pd.DefaultProperty)
                        ////    {
                        ////        vm = new ValidationMessage(SeverityCode.Error, "Wrong default property declaration.", key, false);
                        ////        OnValidation(vm);
                        ////    }
                        ////}

                        //if (pd.IsComposite && !tn.Content.Parameters[key].IsComposite)
                        //{

                        //    //Looking for some other required property except the default.
                        //    foreach (PropertySpecification prop in pd.PropertyDefines.Values)
                        //    {
                        //        if (prop.Using == Using.Required && !tn.Content.Parameters[key].Properties.Contains(prop.Name) && prop.Name != pd.DefaultProperty)
                        //        {
                        //            vm = new ValidationMessage(SeverityCode.Error, "Required property '" + prop.Name + "' not found", key, false);
                        //            OnValidation(vm);
                        //        }
                        //    }
                        //    //Validate none composite parameter aginst the default property of the parameter definition.
                        //    ValidateProperty(tn.Content, tn.Content.Parameters[key], pd.PropertyDefines[pd.DefaultProperty],"~Default");
                        //}
                        //else
                        //{
                        //    foreach (PropertySpecification prop in pd.PropertyDefines.Values)
                        //    {
                        //        if (prop.Using == Using.Required && !tn.Content.Parameters[key].Properties.Contains(prop.Name))
                        //        {
                        //            vm = new ValidationMessage(SeverityCode.Error, "Required property '" + prop.Name + "' not found", key, false);
                        //            OnValidation(vm);

                        //        }
                        //        if (tn.Content.Parameters[key].Properties.Contains(prop.Name))
                        //        {
                        //            ValidateProperty(tn.Content, tn.Content.Parameters[key], prop, prop.Name);
                        //        }
                        //    }
                        //}

                    }
                    else if (pd.RecommendationLevel == 3)
                    {

                        vm = new ValidationMessage(SeverityCode.Warning, "Higly recommended variable not found", key, false);
                        OnValidation(vm);
                    }
                }

                //}
            }
        }

        //private void ValidateProperty(StoryBase sb, Parameter parameter, ParameterSpec pSpec)
        //{
        //    ValidationMessage vm;
        //    //Property p = parameter[targetProperty];
        //    bool cycleFound = false;
        //    foreach (ValueBase vb in parameter.Values)
        //    {
        //        if (vb is Cycle)
        //            cycleFound = true;
        //        ValidateBaseType(parameter, pSpec, vb);
        //    }
        //    if (!pSpec.AllowCycling && cycleFound)
        //    {
        //        vm = new ValidationMessage(SeverityCode.Error, "Cycling is not allowed for this parameter", pSpec.Name, false);
        //        OnValidation(vm);
        //    }

        //    if (pSpec.Fixed)
        //    {
        //        if (sb is StorySplit || parameter.Values.Count > 1)
        //        {
        //            vm = new ValidationMessage(SeverityCode.Error, "A fixed parameter can't be altered", parameter, false);
        //            OnValidation(vm);
        //        }
        //    }
        //}

        private void ValidateBaseType(DynamicTerm p, XeoTerm pSpec, ValueBase vb)
        {
            //ValidationMessage vm;
            //if (vb is Values)
            //{

            //    switch (pSpec.TypeDefine.BaseType)
            //    {
            //        case BaseType.Number:
            //            {
            //                double x;
            //                if (Double.TryParse((vb as Values).Val, out x))
            //                {
            //                    ValidateTypeSpecifica(vb, pSpec);
            //                }
            //                else
            //                {
            //                    vm = new ValidationMessage(SeverityCode.Error, "Basetype proof failed.", vb, false);
            //                    OnValidation(vm);
            //                }
            //                break;
            //            }
            //        case BaseType.Text:
            //            {
            //                ValidateTypeSpecifica(vb, pSpec);
            //                break;
            //            }
            //        case BaseType.Date:
            //            {
            //                DateTime dt;
            //                if (DateTime.TryParse((vb as Values).Val, out dt))
            //                {
            //                    ValidateTypeSpecifica(vb, pSpec);
            //                }
            //                else
            //                {
            //                    vm = new ValidationMessage(SeverityCode.Error, "Basetype proof failed.", vb, false);
            //                    OnValidation(vm);
            //                }
            //                break;
            //            }
            //        case BaseType.Bool:
            //            {
            //                bool x;
            //                if (Boolean.TryParse((vb as Values).Val, out x))
            //                {
            //                    ValidateTypeSpecifica(vb, pSpec);
            //                }
            //                else
            //                {
            //                    vm = new ValidationMessage(SeverityCode.Error, "Basetype proof failed.", vb, false);
            //                    OnValidation(vm);
            //                }
            //                break;
            //            }
            //        default:
            //            break;
            //    }
            //}
            //else if (vb is Cycle)
            //{
            //   Cycle c = vb as Cycle;
            //    foreach (ValueBase vb2 in c.Values)
            //    {
            //        ValidateBaseType(p,pSpec, vb2);
            //    }
            //}
        }

        private void ValidateTypeSpecifica(ValueBase vb, XeoTerm pSpec)
        {
            //ValidationMessage vm;
            //bool enumProofed = false;
            //bool enumHit = false;
            //foreach (TypeSpecifics ts in pSpec.TypeDefine.TypeSpecifica)
            //{


            //    if (ts is Enum)
            //    {
            //        enumProofed = true;
            //        enumHit = enumHit || ts.Match((vb as Values).Val, pSpec.TypeDefine.BaseType);
            //    }
            //    else
            //    {
            //        if (!ts.Match((vb as Values).Val, pSpec.TypeDefine.BaseType))
            //        {
            //            vm = new ValidationMessage(SeverityCode.Error, "Proof failed for " + ts.ToString(), vb, false);
            //            OnValidation(vm);
            //        }
            //    }
            //}
            //if (enumProofed && !enumHit)
            //{
            //    vm = new ValidationMessage(SeverityCode.Error, "Proof failed for enumeration", vb, false);
            //    OnValidation(vm);
            //}
        }
        #endregion

        #region Loading methods
        private string _alias = "";
        //public void Load(string nameSpaceAlias, bool force)
        //{
        //    _alias = nameSpaceAlias;
        //    this.reloadNeeded = true;
        //    Load(force);
        //}

        public void Load(string nameSpaceAlias)
        {
            //if(_alias != nameSpaceAlias)
            //    Load(nameSpaceAlias,true);
            //else
            Load(nameSpaceAlias, false);
        }

        public void Load(string nameSpaceAlias, bool force)
        {
            if (_alias != nameSpaceAlias)
            {
                _alias = nameSpaceAlias;
                reloadNeeded = true;
            }
            if (this.reloadNeeded || force)
            {
                Debug.WriteLine("EnvironmentOntologyHandler. Begin ontology load:" + this.instanceLocation);
                this._varSpecs.Clear();
                this.globalUnits.Clear();
                this.globalTypes.Clear();
                this.contextCollection.Clear();

                TextReader txr = new StringReader(OnlineCacheManager.Instance.DownloadContent(this.instanceLocation));

                XmlDocument xpd = new XmlDocument();
                xpd.Load(txr);
                Init(xpd.CreateNavigator());
                BuildHirachy();

                reloadNeeded = false;
                _ontologyLoadState = OntologyLoadState.Loaded;

                Debug.WriteLine("EnvironmentOntologyHandler. End ontology load:" + this.instanceLocation);
            }
        }

        private void BuildHirachy()
        {
            foreach (XeoTerm item in Terms)
            {
                TermNode currentNode = null;
                for (int i = 0; i < item.GroupLevels.Length; i++)
                {
                    TermNode nextNode = FindSubNode(currentNode, item.GroupLevels[i], "subgroup_of");
                    if (nextNode == null)
                    {
                        nextNode = TermNode.CreateContainerNode(item.GroupLevels[i]);
                        if (i == 0)
                            _nodes.Add(nextNode);
                        else
                            currentNode.AddSubNode(nextNode, "subgroup_of");
                    }
                    currentNode = nextNode;
                }
                TermNode leaf = TermNode.CreateNode(item);
                currentNode.AddSubNode(leaf, "belongs_to");


            }
        }

        private TermNode FindSubNode(TermNode tn, string label, string attribute)
        {
            if (tn == null)
            {
                foreach (var item in this.Nodes)
                {
                    if (item.Label == label)
                        return item; 
                }
            }
            else
            {
                foreach (var item in tn.Childs)
                {
                    if (item.Attribute == attribute && item.Relation.Label == label)
                        return item.Relation;
                }
            }
            return null;
        }

        private void Init(XPathNavigator xpn)
        {
            xpn.MoveToRoot();
            xpn.MoveToChild("Repository", xmlNs);
            this.nameSpace = xpn.GetAttribute("NameSpace", "");

            XPathNavigator resourcesNav = xpn.Clone();
            if (resourcesNav.MoveToChild("Resources", xmlNs))
            {
                XPathNavigator globalTypesNav = resourcesNav.Clone();
                if (globalTypesNav.MoveToChild("TypeSets", xmlNs))
                    InitGlobalType(globalTypesNav);

                XPathNavigator globalUnitsNav = resourcesNav.Clone();
                if (globalUnitsNav.MoveToChild("UnitSets", xmlNs))
                    InitGlobalUnits(globalUnitsNav);

                XPathNavigator contextListNav = resourcesNav.Clone();
                if (contextListNav.MoveToChild("ContextCollection", xmlNs))
                    InitContextList(contextListNav);

            }

            XPathNodeIterator xni = xpn.SelectChildren("Variable", xmlNs);
            while (xni.MoveNext())
            {
                string termId = xni.Current.GetAttribute("TermId", "");
                XeoTerm paramSpec = new XeoTerm(termId, this.nameSpace, _alias);
                paramSpec.Name = xni.Current.GetAttribute("Name", "");
                paramSpec.GroupPath = xni.Current.GetAttribute("Group", "");
                //paramSpec.NameSpace = this.nameSpace;
                //paramSpec.NameSpaceAlias = _alias;
                bool temp;
                Boolean.TryParse(xni.Current.GetAttribute("AllowCycling", ""), out temp);
                //paramSpec.AllowCycling = temp;
                //Boolean.TryParse(xni.Current.GetAttribute("Fixed", ""), out temp);
                //paramSpec.Fixed = temp;
                paramSpec.RecommendationLevel = XmlConvert.ToInt32(xni.Current.GetAttribute("RecommendationLevel", ""));


                if (xni.Current.MoveToChild("Definition", xmlNs))
                {
                    paramSpec.Definition = xni.Current.Value;
                    xni.Current.MoveToParent();
                }

                if (xni.Current.MoveToChild("CommunityUrl", xmlNs))
                {
                    paramSpec.URL = new Uri(xni.Current.Value);
                    xni.Current.MoveToParent();
                }

                XPathNodeIterator xniC = xni.Current.SelectChildren("Context", xmlNs);
                while (xniC.MoveNext())
                {
                    VariableContextSpec pc = new VariableContextSpec();
                    XPathNavigator clone;
                    pc.Name = xniC.Current.GetAttribute("Name", "");
                    pc.Description = this.contextCollection[pc.Name];

                    clone = xniC.Current.Clone();
                    InitTypeDefine(clone, pc);

                    clone = xniC.Current.Clone();
                    InitUnits(clone, pc);

                    clone = xniC.Current.Clone();
                    if (clone.MoveToChild("DefaultValue", xmlNs))
                    {
                        pc.DefaultValue = clone.Value;
                    }

                    clone = xniC.Current.Clone();
                    if (clone.MoveToChild("DefaultCycle", xmlNs))
                    {
                        InitCycle(clone, pc);
                    }
                    paramSpec.ContextCollection.Add(pc.Name, pc);

                }
                this._varSpecs.Add(paramSpec);
                paramSpec.Validation += new EventHandler<ValidationMessage>(paramSpec_Validation);
            }

            //if (xpn.MoveToFirstChild())
            //{

            //    do
            //    {
            //        if (xpn.LocalName == "Parameter")
            //        {
            //            ParameterSpec paramSpec = new ParameterSpec();


            //            paramSpec.Name = xpn.GetAttribute("Name", "");
            //            paramSpec.Group = xpn.GetAttribute("Group", "");
            //            paramSpec.NameSpace = this.nameSpaceUri;
            //            bool temp;
            //            Boolean.TryParse(xpn.GetAttribute("AllowCycling", ""), out temp);
            //            paramSpec.AllowCycling = temp;

            //            Boolean.TryParse(xpn.GetAttribute("Fixed", ""), out temp);
            //            paramSpec.Fixed = temp;

            //            paramSpec.RecommendationLevel = XmlConvert.ToInt32(xpn.GetAttribute("RecommendationLevel", ""));

            //            XPathNavigator clone = xpn.Clone();

            //            //InitTypeDefine(clone, paramSpec);
            //            //clone = xpn.Clone();
            //            //if (clone.MoveToChild("Units", xmlNs))
            //            //{
            //            //    InitUnits(clone, paramSpec);
            //            //}

            //            clone = xpn.Clone();
            //            if (clone.MoveToChild("DefaultValue", xmlNs))
            //            {
            //                paramSpec.DefaultValue = clone.Values;
            //            }

            //            clone = xpn.Clone();
            //            if (clone.MoveToChild("DefaultCycle", xmlNs))
            //            {
            //                InitCycle(clone, paramSpec);
            //            }

            //            clone = xpn.Clone();
            //            if(clone.MoveToChild("OptimalityAspect", xmlNs))
            //            {
            //                paramSpec.Optimality = clone.GetAttribute("Default","");
            //            }

            //            clone = xpn.Clone();
            //            if (clone.MoveToChild("StressAspect", xmlNs))
            //            {
            //                paramSpec.Optimality = clone.GetAttribute("Default","");
            //            }

            //            this.paramDefs.Add( paramSpec);
            //        }
            //    } while (xpn.MoveToNext());
            //}
        }

        void paramSpec_Validation(object sender, ValidationMessage e)
        {
            OnValidation(e);
        }

        private void InitContextList(XPathNavigator contextListNav)
        {
            XPathNodeIterator xni = contextListNav.SelectChildren("Context", xmlNs);
            while (xni.MoveNext())
            {
                string cName = xni.Current.GetAttribute("Name", "");
                string desc = "";
                XPathNavigator xpn = xni.Current.Clone();
                if (xpn.MoveToChild("Description", xmlNs))
                    desc = xpn.Value;
                this.contextCollection.Add(cName, desc);
            }
        }

        private void InitGlobalUnits(XPathNavigator globalTypesNav)
        {
            XPathNodeIterator xni = globalTypesNav.SelectChildren("Units", xmlNs);
            while (xni.MoveNext())
            {
                XPathNavigator xpn = xni.Current.Clone();
                UnitSet us = new UnitSet();
                us.Name = xpn.GetAttribute("Name", "");

                InitUnits(xpn, us);
                             this.globalUnits.Add(us.Name, us);
            }
        }

        private void InitGlobalType(XPathNavigator globalTypesNav)
        {
            XPathNodeIterator xni = globalTypesNav.SelectChildren("TypeDefine", xmlNs);
            while (xni.MoveNext())
            {
                NamedTypeSpecification nts = new NamedTypeSpecification();
                InitTypeDefine(xni.Current.Clone(), nts);
                nts.Name = xni.Current.GetAttribute("Name", "");
                if (this.globalTypes.ContainsKey(nts.Name))
                    this.globalTypes.Remove(nts.Name);
                this.globalTypes.Add(nts.Name, nts);
            }
        }

        //private void InitUseAlso(XPathNavigator xpn, ParameterSpecification pd)
        //{
        //    while(xpn.MoveToChild("Parameter", xmlNs))
        //    {
        //        pd.UseAlso.Add(xpn.Values);
        //    }
        //}

        private void InitCycle(XPathNavigator xpn, VariableContextSpec pd)
        {
            DefaultCycle c = new DefaultCycle();
            //c.Length = TimeSpan.Parse(xpn.GetAttribute("Length", ""));
            if (xpn.MoveToChild("Value", xmlNs))
            {
                do
                {
                    string val = xpn.Value;


                    TimeSpan dur = TimeSpanExtension.Parse(xpn.GetAttribute("Duration", ""), TimeSpanParseOption.DoubleIsHour);
                    c.AddValue(dur, val);
                } while (xpn.MoveToNext("Value", xmlNs));
            }
            pd.DefaultCycle = c;
        }

        private void InitUnits(XPathNavigator xpn, VariableContextSpec pc)
        {
            UnitSet us = new UnitSet();
            if (xpn.MoveToChild("UnitsSource", xmlNs))
            {
                if (!this.globalUnits.TryGetValue(xpn.GetAttribute("unitRef", ""), out us))
                    us = new UnitSet();

            }
            else if (xpn.MoveToChild("Units", xmlNs))
            {
                InitUnits(xpn, us);
            }
            pc.UnitSet = us;
        }

        private void InitUnits(XPathNavigator xpn, UnitSet us)
        {
            if (xpn.MoveToChild("Default", xmlNs))
            {
                Unit u = new Unit();
                u.Name = xpn.GetAttribute("Name", "");
                u.Symbol = xpn.GetAttribute("Symbol", "");
                us.DefaultUnit = u;
                while (xpn.MoveToNext("Unit", xmlNs))
                {
                    ConvertableUnit cu = new ConvertableUnit();
                    cu.Name = xpn.GetAttribute("Name", "");
                    cu.Symbol = xpn.GetAttribute("Symbol", "");
                    cu.ConversionString = xpn.GetAttribute("Conversion", "");
                    cu.DefaultUnit = u;
                    us.ConvertableUnits.Add(cu);
                }
            }
        }

        private void InitTypeDefine(XPathNavigator xpn, TypeSpecification td)
        {
            string basetype = xpn.GetAttribute("BaseType", "");
            switch (basetype)
            {
                case "Number":
                    {
                        td.BaseType = VariableDataTypes.Number;
                        break;
                    }
                case "Text":
                    {
                        td.BaseType = VariableDataTypes.Text;
                        break;
                    }
                case "Date":
                    {
                        td.BaseType = VariableDataTypes.Date;
                        break;
                    }
                case "Boolean":
                    {
                        td.BaseType = VariableDataTypes.Bool;
                        break;
                    }
                default:
                    {
                        td.BaseType = VariableDataTypes.Text;
                        break;
                    }
            }

            if (xpn.MoveToFirstChild())
            {
                do
                {
                    TypeSpecifics ts = null;
                    switch (xpn.LocalName)
                    {
                        case "Min":
                            {
                                ts = new Min();
                                break;
                            }
                        case "Max":
                            {
                                ts = new Max();
                                break;
                            }
                        case "Enum":
                            {
                                ts = new Enum();
                                break;
                            }
                        case "Exclude":
                            {
                                ts = new Exclude();
                                break;
                            }
                        default:
                            break;
                    }

                    if (ts != null)
                    {
                        ts.TextVal = xpn.Value;

                        switch (td.BaseType)
                        {
                            case VariableDataTypes.Number:
                                {
                                    ts.NumberVal = (decimal)xpn.ValueAsDouble;
                                    break;
                                }
                            case VariableDataTypes.Text:
                                {
                                    ts.TextVal = xpn.Value;
                                    break;
                                }
                            case VariableDataTypes.Date:
                                {
                                    ts.DateVal = xpn.ValueAsDateTime;
                                    break;
                                }
                            case VariableDataTypes.Bool:
                                {
                                    ts.BooleanVal = xpn.ValueAsBoolean;
                                    break;
                                }
                            default:
                                {
                                    ts.TextVal = xpn.Value;
                                    break;
                                }
                        }
                        td.TypeSpecifica.Add(ts);
                    }
                } while (xpn.MoveToNext());
            }
        }

        private void InitTypeDefine(XPathNavigator xpn, VariableContextSpec pc)
        {
            TypeSpecification ts = new TypeSpecification();
            if (xpn.MoveToChild("TypeSource", xmlNs))
            {
                NamedTypeSpecification nts;
                if (this.globalTypes.TryGetValue(xpn.GetAttribute("typeRef", ""), out nts))
                    ts = nts;
            }
            else if (xpn.MoveToChild("TypeDefine", xmlNs))
            {
                InitTypeDefine(xpn, ts);
            }
            pc.TypeDefine = ts;
        }
        #endregion

        #region Events
        public event EventHandler<ValidationMessage> Validation;
        protected virtual void OnValidation(ValidationMessage vm)
        {
            if (Validation != null)
                Validation(this, vm);
        }
        #endregion

        #region IOntologyHandler Members
        public object this[string term]
        {
            get
            {
                return Find(term);
            }
        }

        //private string[] ListTerms(string type, bool fqNames)
        //{
        //    Load(_alias, false);
        //    if (type == "Parameter")
        //    {
        //        // List<string> temp = new List<string>();
        //        if (fqNames)
        //            return this._varSpecs.ListIdentifiers();
        //        else
        //        {
        //            List<string> ret = new List<string>();
        //            foreach (VariableSpec ps in this._varSpecs)
        //            {
        //                ret.Add(ps.Name);
        //            }
        //            return ret.ToArray();
        //        }
        //        // return temp.ToArray();
        //    }
        //    else
        //        return new string[0] { };
        //}

        public IXemlComponent Copy()
        {
            EnvironmentOntologyHandler poh = new EnvironmentOntologyHandler();
            poh.NameSpace = this.nameSpace;
            poh.InstanceLocation = this.instanceLocation;
            return poh;
        }

        private bool _autoValidation;
        public bool AutoValidation
        {
            get
            {
                return _autoValidation;
            }
            set
            {
                _autoValidation = value;
            }
        }
        #endregion

        #region IEnvironmentOntologyHandler Members
        public IEnumerable<IDynamicOntologyTerm> Terms
        {
            get
            {
                return _varSpecs;
            }
        }

        public IDynamicOntologyTerm Find(Term param)
        {
            return Find(param.TermId);
        }

        public IDynamicOntologyTerm Find(string termId)
        {
            return this._varSpecs.Find(x => x.TermId.Trim() == termId.Trim());
        }
        #endregion

        #region IHierarchicalView Members
        private List<TermNode> _nodes = new List<TermNode>();
        public IEnumerable<TermNode> Nodes
        {
            get { return _nodes; }
        }

        public TermNode FindNode(IOntologyTerm t)
        {
            return FindNode(t.TermId);

        }

        public TermNode FindNode(string termid)
        {
            foreach (var item in _nodes)
            {
                if (FindNode(item, termid) != null)
                    return FindNode(item, termid);
            }
            return null;
        }

        private TermNode FindNode(TermNode start, string termid)
        {
            TermNode ret = null;
            if (!start.IsContainer && start.Term.TermId == termid)
                ret = start;
            else if (start.IsContainer)
            {
                foreach (var item in start.Childs)
                {
                    if (FindNode(item.Relation, termid) != null)
                        ret = FindNode(item.Relation, termid);
                }
            }
            return ret;
        }
        #endregion


        public event LoadedEventHandler OnLoaded;
    }
}
